#!/usr/bin/env python3
"""
强化JavaScript安全执行器
实现多层安全防护，有效屏蔽危险API和模块
"""

import re
import logging
from typing import List, Set, Dict, Any, Tuple

logger = logging.getLogger(__name__)

class SecureJSExecutor:
    """强化JavaScript安全执行器"""
    
    def __init__(self):
        # JavaScript危险API和对象黑名单
        self.dangerous_apis = {
            # Node.js模块系统
            'require', 'import', '__require', '__import__',
            
            # 进程和系统对象
            'process', 'global', 'globalThis', 'GLOBAL', 'root',
            '__dirname', '__filename', 'module', 'exports',
            
            # 文件系统相关
            'fs', 'path', 'os', 'child_process', 'cluster',
            
            # 网络相关
            'http', 'https', 'net', 'dgram', 'dns', 'url',
            'stream', 'querystring', 'websocket',
            
            # 危险执行函数
            'eval', 'Function', 'setTimeout', 'setInterval',
            'setImmediate', 'clearTimeout', 'clearInterval', 'clearImmediate',
            
            # 缓冲区和二进制
            'Buffer', 'ArrayBuffer', 'SharedArrayBuffer',
            
            # 加密和压缩
            'crypto', 'zlib', 'v8', 'vm',
            
            # 事件和工具
            'events', 'util', 'assert',
            
            # 其他危险API
            'worker_threads', 'inspector', 'repl', 'readline',
            'tty', 'constants', 'punycode'
        }
        
        # 危险的JavaScript语法模式
        self.dangerous_patterns = [
            r'require\s*\(',           # require函数调用
            r'import\s+.*\s+from',     # ES6 import语句
            r'eval\s*\(',              # eval函数调用  
            r'Function\s*\(',          # Function构造器
            r'setTimeout\s*\(',        # setTimeout
            r'setInterval\s*\(',       # setInterval
            r'process\.',              # process对象访问
            r'global\.',               # global对象访问
            r'globalThis\.',           # globalThis访问
            r'__dirname',              # 目录名访问
            r'__filename',             # 文件名访问
            r'module\.',               # module对象访问
            r'exports\.',              # exports对象访问
            r'Buffer\.',               # Buffer对象访问
            r'\.exec\s*\(',            # exec方法调用
            r'\.spawn\s*\(',           # spawn方法调用
            r'\.fork\s*\(',            # fork方法调用
            r'new\s+Function\s*\(',    # new Function
            r'new\s+Worker\s*\(',      # Web Worker
            r'\.readFile',             # 文件读取
            r'\.writeFile',            # 文件写入
            r'\.createReadStream',     # 创建读取流
            r'\.createWriteStream',    # 创建写入流
        ]
        
        # 允许的安全API
        self.allowed_apis = {
            # 基本数据类型和操作
            'String', 'Number', 'Boolean', 'Array', 'Object', 'Date',
            'Math', 'JSON', 'RegExp', 'Error', 'TypeError', 'RangeError',
            
            # 基本集合类型
            'Map', 'Set', 'WeakMap', 'WeakSet',
            
            # 基本函数
            'parseInt', 'parseFloat', 'isNaN', 'isFinite',
            'encodeURI', 'decodeURI', 'encodeURIComponent', 'decodeURIComponent',
            
            # 输出和调试
            'console',
            
            # 基本控制结构
            'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'default',
            'break', 'continue', 'return', 'try', 'catch', 'finally', 'throw',
            
            # 基本运算符和关键字
            'var', 'let', 'const', 'function', 'class', 'extends',
            'typeof', 'instanceof', 'in', 'of', 'new', 'delete',
            'this', 'super', 'static', 'public', 'private', 'protected'
        }
    
    def analyze_js_code(self, code: str) -> Tuple[bool, List[str]]:
        """
        分析JavaScript代码的安全性
        
        Returns:
            (is_safe, violations) - 是否安全和违规项列表
        """
        violations = []
        
        # 1. 检查危险API使用
        dangerous_apis = self._find_dangerous_apis(code)
        if dangerous_apis:
            violations.extend([f"危险API: {api}" for api in dangerous_apis])
        
        # 2. 检查危险语法模式
        dangerous_patterns = self._find_dangerous_patterns(code)
        if dangerous_patterns:
            violations.extend([f"危险语法: {pattern}" for pattern in dangerous_patterns])
        
        # 3. 检查字符串中的危险内容
        string_dangers = self._find_dangerous_strings(code)
        if string_dangers:
            violations.extend([f"危险字符串: {danger}" for danger in string_dangers])
        
        is_safe = len(violations) == 0
        
        return is_safe, violations
    
    def _find_dangerous_apis(self, code: str) -> List[str]:
        """查找代码中的危险API"""
        found_dangerous = []
        
        # 移除注释和字符串
        cleaned_code = self._remove_comments_and_strings(code)
        
        for api in self.dangerous_apis:
            # 检查API是否在代码中出现
            if re.search(rf'\b{re.escape(api)}\b', cleaned_code):
                found_dangerous.append(api)
        
        return list(set(found_dangerous))
    
    def _find_dangerous_patterns(self, code: str) -> List[str]:
        """查找代码中的危险语法模式"""
        found_patterns = []
        
        for pattern in self.dangerous_patterns:
            if re.search(pattern, code, re.IGNORECASE):
                found_patterns.append(pattern)
        
        return found_patterns
    
    def _find_dangerous_strings(self, code: str) -> List[str]:
        """查找字符串中的危险内容"""
        dangerous_strings = []
        
        # 查找字符串字面量
        string_patterns = [
            r'"([^"\\]|\\.)*"',  # 双引号字符串
            r"'([^'\\]|\\.)*'",  # 单引号字符串
            r'`([^`\\]|\\.)*`',  # 模板字符串
        ]
        
        for pattern in string_patterns:
            matches = re.findall(pattern, code)
            for match in matches:
                # 检查字符串内容是否包含危险路径
                if any(danger in match for danger in ['/etc/', '/proc/', '/sys/', '/dev/', '/root/', '/home/']):
                    dangerous_strings.append(match[:50])  # 限制长度
        
        return dangerous_strings
    
    def _remove_comments_and_strings(self, code: str) -> str:
        """移除代码中的注释和字符串字面量"""
        # 简化实现：移除单行注释、多行注释和字符串
        # 移除单行注释
        code = re.sub(r'//.*', '', code)
        # 移除多行注释
        code = re.sub(r'/\*.*?\*/', '', code, flags=re.DOTALL)
        # 移除字符串字面量
        code = re.sub(r'"([^"\\]|\\.)*"', '""', code)
        code = re.sub(r"'([^'\\]|\\.)*'", "''", code)
        code = re.sub(r'`([^`\\]|\\.)*`', '``', code)
        
        return code
    
    def create_secure_js_wrapper(self, original_code: str) -> str:
        """创建安全的JavaScript包装脚本"""
        
        # 分析代码安全性
        is_safe, violations = self.analyze_js_code(original_code)
        
        if not is_safe:
            # 如果代码不安全，创建一个报告违规的脚本
            violation_report = "\\n".join(violations)
            wrapper_script = f'''
// === JavaScript安全沙箱检测到违规操作 ===
console.log("🚫 安全检查失败：检测到以下违规操作：");
console.log("{violation_report}");
console.log("");
console.log("❌ 代码执行被阻止以保护系统安全");
process.exit(1);
'''
        else:
            # 如果代码安全，创建受限执行环境（去掉严格模式以避免兼容性问题）
            wrapper_script = f'''
// === JavaScript安全沙箱执行环境 ===

// 禁用危险的全局对象和函数
if (typeof global !== 'undefined') {{
    global.require = undefined;
    global.process = undefined;
    global.Buffer = undefined;
    global.__dirname = undefined;
    global.__filename = undefined;
    global.module = undefined;
    global.exports = undefined;
}}

// 创建安全的函数替代品（避免严格模式冲突）
(function() {{
    // 保存原始函数的引用（如果存在）
    const originalEval = typeof eval !== 'undefined' ? eval : null;
    const originalFunction = typeof Function !== 'undefined' ? Function : null;
    
    // 重写危险函数为抛出错误的函数
    if (typeof globalThis !== 'undefined') {{
        try {{
            globalThis.eval = function() {{
                throw new Error("eval() 被禁用");
            }};
            globalThis.Function = function() {{
                throw new Error("Function() 构造器被禁用");
            }};
            globalThis.setTimeout = function() {{
                throw new Error("setTimeout() 被禁用");
            }};
            globalThis.setInterval = function() {{
                throw new Error("setInterval() 被禁用");
            }};
        }} catch (e) {{
            // 忽略严格模式下的错误
        }}
    }}
}})();

// 在沙箱环境中执行用户代码
try {{
    // 用户代码
{self._indent_code(original_code, '    ')}
}} catch (error) {{
    console.error("代码执行出错:", error.message);
    process.exit(1);
}}
'''
        
        return wrapper_script
    
    def _indent_code(self, code: str, indent: str) -> str:
        """为代码添加缩进"""
        lines = code.split('\n')
        indented_lines = []
        for line in lines:
            if line.strip():
                indented_lines.append(indent + line)
            else:
                indented_lines.append('')
        return '\n'.join(indented_lines)
    
    def create_restricted_node_command(self, script_file: str, timeout_seconds: int = 10) -> List[str]:
        """创建受限的Node.js执行命令"""
        return [
            "timeout", f"{timeout_seconds}s",
            "node", 
            "--no-warnings",
            "--no-deprecation",
            "--max-old-space-size=64",     # 限制堆内存64MB
            "--max-semi-space-size=32",    # 限制半空间32MB
            "--disallow-code-generation-from-strings",  # 禁止从字符串生成代码
            script_file
        ]

if __name__ == "__main__":
    # 测试代码
    executor = SecureJSExecutor()
    
    # 测试危险代码
    dangerous_code = '''
    const fs = require('fs');
    console.log(fs.readFileSync('/etc/passwd', 'utf8'));
    '''
    
    is_safe, violations = executor.analyze_js_code(dangerous_code)
    print(f"代码安全性: {is_safe}")
    print(f"违规项: {violations}")
    
    wrapper = executor.create_secure_js_wrapper(dangerous_code)
    print("生成的安全包装脚本:")
    print(wrapper) 